package com.briup.pai.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.briup.pai.common.constant.AuthConstant;
import com.briup.pai.common.enums.ResultCodeEnum;
import com.briup.pai.common.exception.BriupAssert;
import com.briup.pai.convert.RoleConvert;
import com.briup.pai.dao.RoleMapper;
import com.briup.pai.entity.dto.RoleSaveDTO;
import com.briup.pai.entity.po.Role;
import com.briup.pai.entity.po.RolePermission;
import com.briup.pai.entity.po.UserRole;
import com.briup.pai.entity.vo.RoleQueryVO;
import com.briup.pai.service.IRolePermissionService;
import com.briup.pai.service.IRoleService;
import com.briup.pai.service.IUserRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@CacheConfig(cacheNames = AuthConstant.ROLE_CACHE_PREFIX)
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {


    @Autowired
    private IUserRoleService userRoleService;
    @Autowired
    private IRolePermissionService rolePermissionService;

    @Autowired
    private RoleConvert roleConvert;

    @Override
    @Cacheable(key = "T(com.briup.pai.common.constant.CommonConstant).LIST_CACHE_PREFIX")
    public List<RoleQueryVO> getAllRoles() {
        return roleConvert.po2RoleQueryVOList(list());
    }

    @Override
    @Transactional
    // 更新当前的缓存，删除别的地方的查询role的缓存
    @Caching(put = @CachePut(key = "#result.id"),
            evict = {
            @CacheEvict(key = "T(com.briup.pai.common.constant.CommonConstant).LIST_CACHE_PREFIX"),
            @CacheEvict(key = "T(com.briup.pai.common.constant.AuthConstant).GET_ALL_ROLES_CACHE_KEY")
    })
    public RoleQueryVO addOrModifyRole(RoleSaveDTO roleSaveDTO) {
        Integer roleId = roleSaveDTO.getRoleId();
        String roleName = roleSaveDTO.getRoleName();
        // 角色名称不能为空
        BriupAssert.requireNotNull(
                roleName,
                ResultCodeEnum.PARAM_IS_ERROR
        );
        Role role;
        if(ObjectUtil.isEmpty(roleId)){
            // 角色名称不能重复
            BriupAssert.requireNull(
                    this,
                    Role::getRoleName,
                    roleName,
                    ResultCodeEnum.DATA_ALREADY_EXIST
            );
            role = roleConvert.roleSaveDTO2Po(roleSaveDTO);
            save(role);
        }else {
            BriupAssert.requireNotNull(
                    this,
                    Role::getId,
                    roleId,
                    ResultCodeEnum.DATA_NOT_EXIST
            );
            // 角色名称不能重复
            BriupAssert.requireNull(
                    this,
                    Role::getRoleName,
                    roleName,
                    Role::getId,
                    roleId,
                    ResultCodeEnum.DATA_ALREADY_EXIST
            );
            role = roleConvert.roleSaveDTO2Po(roleSaveDTO);
            updateById(role);
        }
        return roleConvert.po2RoleQueryVO(role);
    }

    @Override
    @Cacheable(key = "#roleId")
    public RoleQueryVO getRoleById(Integer roleId) {
        return roleConvert.po2RoleQueryVO(BriupAssert.requireNotNull(
                this,
                Role::getId,
                roleId,
                ResultCodeEnum.DATA_NOT_EXIST
        ));
    }

    @Override
    @Transactional
    // 缓存也可以指定某个key的批量删除
    @Caching(evict = {
            @CacheEvict(key = "T(com.briup.pai.common.constant.CommonConstant).LIST_CACHE_PREFIX"),
            @CacheEvict(key = "#roleId"),
            @CacheEvict(cacheNames = AuthConstant.AUTH_CACHE_PREFIX, allEntries = true)
    })
    public void removeRoleById(Integer roleId) {
        BriupAssert.requireNotNull(
                this,
                Role::getId,
                roleId,
                ResultCodeEnum.DATA_NOT_EXIST
        );
        // 删除角色-权限的关联
        LambdaQueryWrapper<RolePermission> rpLqw = new LambdaQueryWrapper<>();
        rpLqw.eq(RolePermission::getRoleId,roleId);
        rolePermissionService.remove(rpLqw);
        // 删除用户-角色的关联
        LambdaQueryWrapper<UserRole> urLqw = new LambdaQueryWrapper<>();
        urLqw.eq(UserRole::getRoleId,roleId);
        userRoleService.remove(urLqw);
        // 删除角色
        removeById(roleId);
    }
}